diff -rcNP og/Documentation/admin-guide/sysctl/fs.rst linux-5.4.116/Documentation/admin-guide/sysctl/fs.rst
*** og/Documentation/admin-guide/sysctl/fs.rst	2021-05-02 12:05:04.000000000 +0300
--- linux-5.4.116/Documentation/admin-guide/sysctl/fs.rst	2021-05-04 14:44:03.000000000 +0300
***************
*** 48,53 ****
--- 48,54 ----
  - suid_dumpable
  - super-max
  - super-nr
+ - sysfs_restrict
  
  
  aio-nr & aio-max-nr
***************
*** 272,277 ****
--- 273,303 ----
  This protection is based on the restrictions in Openwall and grsecurity.
  
  
+ sysfs_restrict
+ --------------
+ 
+ This toggle controls the permissions of sysfs (the pseudo-filesystem
+ mounted at /sys).
+ 
+ When sysfs_restrict is set to (0), there are no restrictions and
+ unprivileged users are permitted to access sysfs. When sysfs_restrict
+ is set to (1), sysfs and any filesystem normally mounted under
+ it (e.g. debugfs) will be accessible only by root.
+ 
+ These filesystems generally provide access to hardware and debug information
+ that isn't appropriate for unprivileged users of the system. Sysfs and
+ debugfs have also become a large source of new vulnerabilities, ranging
+ from infoleaks to local compromise. There has been very little oversight with
+ an eye toward security involved in adding new exporters of information to these
+ filesystems, so their use is discouraged.
+ 
+ This is disabled by default as many programs (e.g. Xorg or debugging tools)
+ require access to sysfs/debugfs.
+ 
+ The kernel config option CONFIG_SECURITY_SYSFS_RESTRICT sets the default value
+ of sysfs_restrict.
+ 
+ 
  suid_dumpable:
  --------------
  
diff -rcNP og/fs/debugfs/inode.c linux-5.4.116/fs/debugfs/inode.c
*** og/fs/debugfs/inode.c	2021-05-02 12:05:04.000000000 +0300
--- linux-5.4.116/fs/debugfs/inode.c	2021-05-04 14:47:28.000000000 +0300
***************
*** 27,32 ****
--- 27,33 ----
  #include <linux/magic.h>
  #include <linux/slab.h>
  #include <linux/security.h>
+ #include <linux/sysfs.h>
  
  #include "internal.h"
  
***************
*** 562,568 ****
  		return failed_creating(dentry);
  	}
  
! 	inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
  	inode->i_op = &debugfs_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  
--- 563,572 ----
  		return failed_creating(dentry);
  	}
  
! 	inode->i_mode = S_IRWXU;
! 	if (!sysfs_restrict)
! 		inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
! 
  	inode->i_op = &debugfs_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  
***************
*** 913,916 ****
  	return retval;
  }
  core_initcall(debugfs_init);
- 
--- 917,919 ----
diff -rcNP og/fs/sysfs/dir.c linux-5.4.116/fs/sysfs/dir.c
*** og/fs/sysfs/dir.c	2021-05-02 12:05:04.000000000 +0300
--- linux-5.4.116/fs/sysfs/dir.c	2021-05-04 14:45:18.000000000 +0300
***************
*** 32,37 ****
--- 32,39 ----
  	kfree(buf);
  }
  
+ int sysfs_restrict = IS_ENABLED(CONFIG_SECURITY_SYSFS_RESTRICT);
+ 
  /**
   * sysfs_create_dir_ns - create a directory for an object with a namespace tag
   * @kobj: object we're creating directory for
***************
*** 40,45 ****
--- 42,48 ----
  int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
  {
  	struct kernfs_node *parent, *kn;
+ 	umode_t *mode = S_IRWXU;
  	kuid_t uid;
  	kgid_t gid;
  
***************
*** 56,63 ****
  
  	kobject_get_ownership(kobj, &uid, &gid);
  
  	kn = kernfs_create_dir_ns(parent, kobject_name(kobj),
! 				  S_IRWXU | S_IRUGO | S_IXUGO, uid, gid,
  				  kobj, ns);
  	if (IS_ERR(kn)) {
  		if (PTR_ERR(kn) == -EEXIST)
--- 59,69 ----
  
  	kobject_get_ownership(kobj, &uid, &gid);
  
+ 	if (!sysfs_restrict)
+ 		mode = S_IRWXU | S_IRUGO | S_IXUGO;
+ 
  	kn = kernfs_create_dir_ns(parent, kobject_name(kobj),
! 					mode, uid, gid,
  				  kobj, ns);
  	if (IS_ERR(kn)) {
  		if (PTR_ERR(kn) == -EEXIST)
diff -rcNP og/include/linux/sysfs.h linux-5.4.116/include/linux/sysfs.h
*** og/include/linux/sysfs.h	2021-05-02 12:05:04.000000000 +0300
--- linux-5.4.116/include/linux/sysfs.h	2021-05-04 14:36:37.000000000 +0300
***************
*** 305,310 ****
--- 305,312 ----
  
  int __must_check sysfs_init(void);
  
+ extern int sysfs_restrict;
+ 
  static inline void sysfs_enable_ns(struct kernfs_node *kn)
  {
  	return kernfs_enable_ns(kn);
diff -rcNP og/kernel/sysctl.c linux-5.4.116/kernel/sysctl.c
*** og/kernel/sysctl.c	2021-05-04 14:23:10.000000000 +0300
--- linux-5.4.116/kernel/sysctl.c	2021-05-04 14:45:52.000000000 +0300
***************
*** 69,74 ****
--- 69,75 ----
  #include <linux/mount.h>
  #include <linux/userfaultfd_k.h>
  #include <linux/ipc.h>
+ #include <linux/sysfs.h>
  
  #include "../lib/kstrtox.h"
  
***************
*** 1395,1401 ****
  		.proc_handler	= overcommit_kbytes_handler,
  	},
  	{
! 		.procname	= "page-cluster", 
  		.data		= &page_cluster,
  		.maxlen		= sizeof(int),
  		.mode		= 0644,
--- 1396,1402 ----
  		.proc_handler	= overcommit_kbytes_handler,
  	},
  	{
! 		.procname	= "page-cluster",
  		.data		= &page_cluster,
  		.maxlen		= sizeof(int),
  		.mode		= 0644,
***************
*** 1913,1919 ****
  		.mode		= 0555,
  		.child		= inotify_table,
  	},
! #endif	
  #ifdef CONFIG_EPOLL
  	{
  		.procname	= "epoll",
--- 1914,1920 ----
  		.mode		= 0555,
  		.child		= inotify_table,
  	},
! #endif
  #ifdef CONFIG_EPOLL
  	{
  		.procname	= "epoll",
***************
*** 1967,1972 ****
--- 1968,1984 ----
  		.extra1		= SYSCTL_ZERO,
  		.extra2		= &two,
  	},
+ #ifdef CONFIG_SYSFS
+ 	{
+ 		.procname	= "sysfs_restrict",
+ 		.data		= &sysfs_restrict,
+ 		.maxlen		= sizeof(int),
+ 		.mode		= 0600,
+ 		.proc_handler	= proc_dointvec_minmax_sysadmin,
+ 		.extra1		= SYSCTL_ZERO,
+ 		.extra2		= SYSCTL_ONE,
+ 	},
+ #endif
  #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
  	{
  		.procname	= "binfmt_misc",
***************
*** 2394,2405 ****
  	int *i, vleft, first = 1, err = 0;
  	size_t left;
  	char *kbuf = NULL, *p;
! 	
  	if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
  		*lenp = 0;
  		return 0;
  	}
! 	
  	i = (int *) tbl_data;
  	vleft = table->maxlen / sizeof(*i);
  	left = *lenp;
--- 2406,2417 ----
  	int *i, vleft, first = 1, err = 0;
  	size_t left;
  	char *kbuf = NULL, *p;
! 
  	if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
  		*lenp = 0;
  		return 0;
  	}
! 
  	i = (int *) tbl_data;
  	vleft = table->maxlen / sizeof(*i);
  	left = *lenp;
***************
*** 2625,2631 ****
   * @ppos: file position
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string. 
   *
   * Returns 0 on success.
   */
--- 2637,2643 ----
   * @ppos: file position
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string.
   *
   * Returns 0 on success.
   */
***************
*** 3138,3144 ****
   * @ppos: file position
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string. 
   * The values read are assumed to be in seconds, and are converted into
   * jiffies.
   *
--- 3150,3156 ----
   * @ppos: file position
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string.
   * The values read are assumed to be in seconds, and are converted into
   * jiffies.
   *
***************
*** 3160,3167 ****
   * @ppos: pointer to the file position
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string. 
!  * The values read are assumed to be in 1/USER_HZ seconds, and 
   * are converted into jiffies.
   *
   * Returns 0 on success.
--- 3172,3179 ----
   * @ppos: pointer to the file position
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string.
!  * The values read are assumed to be in 1/USER_HZ seconds, and
   * are converted into jiffies.
   *
   * Returns 0 on success.
***************
*** 3183,3190 ****
   * @ppos: the current position in the file
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string. 
!  * The values read are assumed to be in 1/1000 seconds, and 
   * are converted into jiffies.
   *
   * Returns 0 on success.
--- 3195,3202 ----
   * @ppos: the current position in the file
   *
   * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
!  * values from/to the user buffer, treated as an ASCII string.
!  * The values read are assumed to be in 1/1000 seconds, and
   * are converted into jiffies.
   *
   * Returns 0 on success.
diff -rcNP og/security/Kconfig linux-5.4.116/security/Kconfig
*** og/security/Kconfig	2021-05-04 14:23:10.000000000 +0300
--- linux-5.4.116/security/Kconfig	2021-05-04 14:43:04.000000000 +0300
***************
*** 64,69 ****
--- 64,92 ----
  
  	  If unsure say N.
  
+ config SECURITY_SYSFS_RESTRICT
+ 	bool "Sysfs/debugfs restriction"
+ 	default n
+ 	depends on SYSFS
+ 	help
+ 	  If you say Y here, sysfs (the pseudo-filesystem mounted at /sys) and
+ 	  any filesystem normally mounted under it (e.g. debugfs) will be
+ 		accessible only by root. These filesystems generally provide access
+ 	  to hardware and debug information that isn't appropriate for unprivileged
+ 		users of the system. Sysfs and debugfs have also become a large source
+ 	  of new vulnerabilities, ranging from infoleaks to local compromise.
+ 	  There has been very little oversight with an eye toward security involved
+ 	  in adding new exporters of information to these filesystems, so their
+ 	  use is discouraged.
+ 
+ 		This is disabled by default as many programs (e.g. Xorg or debugging tools)
+ 	  require access to sysfs/debugfs.
+ 
+ 	  This setting can be overridden at runtime via the
+ 	  fs.sysfs_restrict sysctl.
+ 
+ 	  If unsure say N.
+ 
  config SECURITY
  	bool "Enable different security models"
  	depends on SYSFS
